package cn.infrabase.http;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

/**
 * <pre>
 * 网址，如：{@code http://host.com:8080/p/a/t/h?query=string#hash}
 * ┌──────────────────────────────────────────────────────────────────────┐
 * │                                href                                  │
 * ├──────────┬───┬───────────────────┬───────────────────────────┬───────┤
 * │ protocol │   │      host         │           path            │ hash  │
 * ├──────────┼───┼──────────┬─┬──────┼──────────┬────────────────┤       │
 * │ protocol │   │ hostname │ │ port │ pathname │     search     │       │
 * │          │   │          │ │      │          ├─┬──────────────┤       │
 * │          │   │          │ │      │          │ │    query     │       │
 * │ http     │://│ host.com │:│ 8080 │ /p/a/t/h │?│ query=string │ #hash │
 * │          │   │          │ │      │          │ │              │       │
 * └──────────┴───┴──────────┴─┴──────┴──────────┴─┴──────────────┴───────┘
 * </pre>
 *
 * @author Weimin Gao
 * @since 1.0.0
 **/
@Builder
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
public class Url {

    /**
     * 网址协议，如：http
     */
    private UrlProtocol protocol;

    /**
     * 网址主机名，如：host.com
     */
    private String hostname;

    /**
     * 网址端口，如：8080
     */
    private int port;

    /**
     * 网址路径，如：/a/b
     */
    private String pathname;

    /**
     * 网址参数，如：name=zhangsan&age=20
     */
    private String query;

    /**
     * 网址描点，如：#tag
     */
    private String hash;

    /**
     * 返回网址协议。
     *
     * @return 网址协议。
     */
    public UrlProtocol protocol() {
        return protocol;
    }

    /**
     * 返回网址主机名，如：infrabase.cn。
     *
     * @return 网址主机名。
     */
    public String hostname() {
        return hostname;
    }

    /**
     * 返回网址主机名加冒号端口，如果网址端口为协议默认端口时直接返回主机名。
     *
     * @return 网址主机名加冒号端口。
     */
    public String host() {
        if (protocol.isHttp() && port == UrlProtocol.HTTP_PORT) {
            return hostname;
        } else {
            if (protocol.isHttps() && port == UrlProtocol.HTTPS_PORT) {
                return hostname;
            } else {
                return hostname + ":" + port;
            }
        }
    }

    /**
     * 返回网址端口。
     *
     * @return 网址端口。
     */
    public int port() {
        return port;
    }

    /**
     * 返回网址路径，如：/a/b。
     *
     * @return 网址路径。
     */
    public String pathname() {
        if (pathname == null) {
            return "";
        }
        return pathname;
    }

    /**
     * 返回网址参数。
     *
     * @return 网址参数。
     */
    public String query() {
        if (query == null) {
            return "";
        }
        return query;
    }

    /**
     * 返回问号加网址参数，如果网址参数为空直接返回空字符串。
     *
     * @return 问号加网址参数。
     */
    public String search() {
        String query = query();
        if (query == null || "".equals(query)) {
            return "";
        } else {
            return "?" + query;
        }
    }

    /**
     * 返回网址描点。
     *
     * @return 网址描点。
     */
    public String hash() {
        if (hash == null || "".equals(hash)) {
            return "";
        }
        return "#" + hash;
    }

    /**
     * 返回网址路径加问号加参数加锚点。
     *
     * @return 网址路径加问号加参数加锚点。
     */
    public String path() {
        return pathname() + search();
    }

    /**
     * 返回请求地址链接。
     *
     * @return 请求连接地址。
     */
    public String href() {
        return protocol.name() + "://" + host() + path() + hash();
    }

    @Override
    public String toString() {
        return href();
    }
}
